r.y = child->y;
r.width = child->width;
r.height = child->height;
-
+
child_region = gdk_region_rectangle (&r);
+
+ if (child->shape)
+ gdk_region_intersect (child_region, child->shape);
+ else if (private->window_type == GDK_WINDOW_FOREIGN)
+ {
+ GdkRegion *shape;
+ shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
+ if (shape)
+ {
+ gdk_region_intersect (child_region, shape);
+ gdk_region_destroy (shape);
+ }
+ }
+
gdk_region_subtract (region, child_region);
gdk_region_destroy (child_region);
+
}
}
r.width = private->width;
r.height = private->height;
new_clip = gdk_region_rectangle (&r);
-
+
if (private->parent != NULL && GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
{
gdk_region_intersect (new_clip, private->parent->clip_region);
/* Convert from parent coords to window coords */
gdk_region_offset (new_clip, -private->x, -private->y);
+ if (private->shape)
+ gdk_region_intersect (new_clip, private->shape);
+
if (private->clip_region == NULL ||
!gdk_region_equal (private->clip_region, new_clip))
clip_region_changed = TRUE;
gdk_window_has_impl (private) &&
/* Not for offscreens */
private->window_type != GDK_WINDOW_OFFSCREEN &&
- /* or for toplevels */
- private->parent != NULL &&
- GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT &&
+ /* or for non-shaped toplevels */
+ (private->shaped ||
+ (private->parent != NULL &&
+ GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)) &&
/* or for foreign windows */
GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN
)
gint y)
{
GdkWindowObject *private;
+ GdkRegion *region;
g_return_if_fail (GDK_IS_WINDOW (window));
private = (GdkWindowObject *) window;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_mask (window, mask, x, y);
+ region = _gdk_windowing_get_shape_for_mask (mask);
+
+ gdk_window_shape_combine_region (window,
+ region,
+ x, y);
+
+ gdk_region_destroy (region);
}
/**
private = (GdkWindowObject *) window;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region (window, shape_region, offset_x, offset_y);
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ private->shaped = (shape_region != NULL);
+
+ if (private->shape)
+ gdk_region_destroy (private->shape);
+
+ if (shape_region)
+ {
+ private->shape = gdk_region_copy (shape_region);
+ gdk_region_offset (private->shape, offset_x, offset_y);
+ }
+ else
+ private->shape = NULL;
+
+ recompute_visible_regions (private, TRUE, FALSE);
+}
+
+static void
+do_child_shapes (GdkWindow *window,
+ gboolean merge)
+{
+ GdkWindowObject *private;
+ GdkRectangle r;
+ GdkRegion *region;
+
+ private = (GdkWindowObject *) window;
+
+ r.x = 0;
+ r.y = 0;
+ r.width = private->width;
+ r.height = private->height;
+
+ region = gdk_region_rectangle (&r);
+ remove_child_area (private, NULL, region);
+
+ if (merge && private->shape)
+ gdk_region_subtract (region, private->shape);
+
+ gdk_window_shape_combine_region (window, region, 0, 0);
}
/**
void
gdk_window_set_child_shapes (GdkWindow *window)
{
- GdkWindowObject *private;
-
g_return_if_fail (GDK_IS_WINDOW (window));
- private = (GdkWindowObject *) window;
-
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_child_shapes (window);
+ do_child_shapes (window, FALSE);
}
/**
void
gdk_window_merge_child_shapes (GdkWindow *window)
{
- GdkWindowObject *private;
-
g_return_if_fail (GDK_IS_WINDOW (window));
- private = (GdkWindowObject *) window;
-
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->merge_child_shapes (window);
+ do_child_shapes (window, TRUE);
}
point_in_window (GdkWindowObject *window,
double x, double y)
{
- /* TODO: Input Shape */
return
x >= 0 && x < window->width &&
- y >= 0 && y < window->height;
+ y >= 0 && y < window->height &&
+ (window->shape == NULL ||
+ gdk_region_point_in (window->shape,
+ x, y));
}
static void
return;
}
-GdkRegion *
-_gdk_windowing_window_get_shape (GdkWindow *window)
+static GdkRegion *
+xwindow_get_shape (Display *xdisplay,
+ Window window)
{
GdkRegion *shape;
+ GdkRectangle *rl;
+ XRectangle *xrl;
+ gint rn, ord, i;
shape = NULL;
#if defined(HAVE_SHAPE_EXT)
- if (!GDK_WINDOW_DESTROYED (window) &&
- gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
+ xrl = XShapeGetRectangles (xdisplay,
+ window,
+ ShapeBounding, &rn, &ord);
+
+ if (rn == 0)
+ return NULL;
+
+ if (ord != YXBanded)
{
- GdkRectangle *rl;
- XRectangle *xrl;
- gint rn, ord, i;
-
- xrl = XShapeGetRectangles (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- ShapeBounding, &rn, &ord);
-
- if (ord != YXBanded)
- {
- /* This really shouldn't happen with any xserver, as they
- generally convert regions to YXBanded internally */
- g_warning ("non YXBanded shape masks not supported");
- XFree (rl);
- return NULL;
- }
+ /* This really shouldn't happen with any xserver, as they
+ generally convert regions to YXBanded internally */
+ g_warning ("non YXBanded shape masks not supported");
+ XFree (xrl);
+ return NULL;
+ }
- rl = g_new (GdkRectangle, rn);
- for (i = 0; i < rn; i++)
- {
- rl[i].x = xrl[i].x;
- rl[i].y = xrl[i].y;
- rl[i].width = xrl[i].width;
- rl[i].height = xrl[i].height;
- }
-
- shape = _gdk_region_new_from_yxbanded_rects (rl, rn);
- g_free (rl);
- XFree (rl);
+ rl = g_new (GdkRectangle, rn);
+ for (i = 0; i < rn; i++)
+ {
+ rl[i].x = xrl[i].x;
+ rl[i].y = xrl[i].y;
+ rl[i].width = xrl[i].width;
+ rl[i].height = xrl[i].height;
}
+ XFree (xrl);
+
+ shape = _gdk_region_new_from_yxbanded_rects (rl, rn);
+ g_free (rl);
+#endif
+
+ return shape;
+}
+
+
+GdkRegion *
+_gdk_windowing_get_shape_for_mask (GdkBitmap *mask)
+{
+ GdkDisplay *display;
+ Window window;
+ GdkRegion *region;
+
+ display = gdk_drawable_get_display (GDK_DRAWABLE (mask));
+
+ window = XCreateSimpleWindow (GDK_DISPLAY_XDISPLAY (display),
+ GDK_SCREEN_XROOTWIN (gdk_display_get_default_screen (display)),
+ -1, -1, 1, 1, 0,
+ 0, 0);
+ XShapeCombineMask (GDK_DISPLAY_XDISPLAY (display),
+ window,
+ ShapeBounding,
+ 0, 0,
+ GDK_PIXMAP_XID (mask),
+ ShapeSet);
+
+ region = xwindow_get_shape (GDK_DISPLAY_XDISPLAY (display),
+ window);
+
+ XDestroyWindow (GDK_DISPLAY_XDISPLAY (display),
+ window);
+
+ return region;
+}
+
+GdkRegion *
+_gdk_windowing_window_get_shape (GdkWindow *window)
+{
+#if defined(HAVE_SHAPE_EXT)
+ if (!GDK_WINDOW_DESTROYED (window) &&
+ gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
+ return xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window));
#endif
+
+ return NULL;
}
static void